home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------------*\
- | transparent bitmap and DIB routines.
- |
- | in this 'C' you can find the following functions.
- |
- | MaskBlt() - draw a bitmap through a mono mask.
- | TransBlt() - draw a bitmap with one color transparent.
- | TransStretchDIBits() - draw a dib with one color transparent.
- |
- | these functions take advantage of the display driver, if it supports
- | transparent operations.
- |
- |
- | - ToddLa
- |
- \*----------------------------------------------------------------------------*/
-
- #include <windows.h>
-
- #ifndef C1_TRANSPARENT
- #define CAPS1 94 /* other caps */
- #define C1_TRANSPARENT 0x0001 /* new raster cap */
- #define TRANSPARENT1 3 /* use with SetBkMode() */
- #endif /* ifndef C1_TRANSPARENT */
-
- #define DSna 0x00220326L
- #define DSa 0x008800C6L
- #define DSo 0x00EE0086L
- #define DSx 0x00660046L
-
- #define rgbBlack RGB(0,0,0)
- #define rgbWhite RGB(255,255,255)
-
- #define RGBQ(rgb) RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb))
-
- //
- // MaskBlt
- //
- // use this for a true mask blt
- //
- void TrueMaskBlt (HDC hdcD,int x,int y,int dx,int dy,HDC hdcS,HDC hdcMask,int x0,int y0)
- {
- COLORREF rgbBk,rgbFg;
-
- rgbBk = SetBkColor(hdcD,rgbWhite);
- rgbFg = SetTextColor(hdcD,rgbBlack);
-
- BitBlt(hdcD,x,y,dx,dy,hdcS, x0,y0,DSx);
- BitBlt(hdcD,x,y,dx,dy,hdcMask,x0,y0,DSa);
- BitBlt(hdcD,x,y,dx,dy,hdcS, x0,y0,DSx);
-
- SetBkColor(hdcD,rgbBk);
- SetTextColor(hdcD,rgbFg);
- }
-
- //
- // TransMaskBlt
- //
- // use this for a mask blt where the source (hdcS) has black (ie 0)
- // every where the mask has white (ie 1)
- //
- void TransMaskBlt (HDC hdcD,int x,int y,int dx,int dy,HDC hdcS,HDC hdcMask,int x0,int y0)
- {
- COLORREF rgbBk,rgbFg;
-
- rgbBk = SetBkColor(hdcD,rgbWhite);
- rgbFg = SetTextColor(hdcD,rgbBlack);
-
- BitBlt(hdcD,x,y,dx,dy,hdcMask,x0,y0,DSa);
- BitBlt(hdcD,x,y,dx,dy,hdcS, x0,y0,DSo);
-
- SetBkColor(hdcD,rgbBk);
- SetTextColor(hdcD,rgbFg);
- }
-
- //
- // MakeMonoMask
- //
- // builds a transparent mask that you can use to draw (using TransMaskBlt)
- // the given bitmap causing the given color to be transparent
- //
- HBITMAP MakeTransMask(HBITMAP hbm, HPALETTE hpal, COLORREF rgb)
- {
- HDC hdcS;
- HDC hdc=NULL;
- HBITMAP hbmMask=NULL;
- HDC hdcMask=NULL;
- BITMAP bm;
- int dx,dy;
-
- GetObject(hbm, sizeof(bm), &bm);
- dx = bm.bmWidth;
- dy = bm.bmHeight;
-
- hdcS = GetDC(NULL);
- hdcMask = CreateCompatibleDC(hdcS);
- hdc = CreateCompatibleDC(hdcS);
- ReleaseDC(NULL, hdcS);
-
- if (!hdc || !hdcMask)
- goto exit;
-
- SelectObject(hdc, hbm);
-
- if (hpal)
- {
- SelectPalette(hdc, hpal, FALSE);
- RealizePalette(hdc);
-
- SelectPalette(hdcMask, hpal, FALSE);
- RealizePalette(hdcMask);
- }
-
- //
- // use upper left corner as transparent color.
- //
- if (rgb == (COLORREF)-1)
- rgb = GetPixel(hdc, 0, 0) | 0x02000000; //!!!make a PALETTERGB()
-
- //
- // create a mask bitmap and associated DC
- //
- hbmMask = CreateBitmap(dx, dy, 1, 1, NULL);
-
- if (!hbmMask)
- goto exit;
-
- SelectObject(hdcMask, hbmMask);
-
- // do a color to mono bitblt to build the mask
- // generate 1's where the source is equal to the background, else 0's
-
- SetBkColor(hdc, rgb);
- BitBlt(hdcMask, 0, 0, dx, dy, hdc, 0, 0, SRCCOPY);
-
- // make all background pixels in the source BLACK
-
- SetBkColor(hdc,rgb);
- BitBlt(hdc,0,0,dx,dy,hdcMask,0,0,DSx);
-
- exit:
- if (hdcMask)
- DeleteDC(hdcMask);
-
- if (hdc)
- DeleteDC(hdc);
-
- return hbmMask;
- }
-
- //
- // TransBlt
- //
- // Transparent bitblt that uses the current
- // background color of the DC as the transparent color.
- //
- BOOL TransBlt(HDC hdcD,int x,int y,int dx,int dy,HDC hdcS,int x0,int y0)
- {
- DWORD rgbBk,rgbFg;
- DWORD rgbBkS;
- HBITMAP hbmMask;
- HDC hdcMask;
- HBITMAP hbmT;
- BOOL f = FALSE;
-
- //
- // see if the device supports this call directly
- //
- // otherwise we need to simulate it.
- //
- #ifndef WIN32
- if (GetDeviceCaps(hdcD, CAPS1) & C1_TRANSPARENT)
- {
- WORD w;
- w = SetBkMode(hdcD, TRANSPARENT1);
- f = BitBlt(hdcD,x,y,dx,dy,hdcS,x0,y0,SRCCOPY);
- SetBkMode(hdcD, w);
- return f;
- }
- #endif
-
- //
- // Get the current DC color's
- //
- rgbBk = GetBkColor(hdcD);
- rgbFg = GetTextColor(hdcD);
- rgbBkS= GetBkColor(hdcS);
-
- SetTextColor(hdcD,rgbBlack);
-
- //
- // make a memory DC for use in color conversion
- //
- hdcMask = CreateCompatibleDC(hdcS);
-
- if (!hdcMask)
- return FALSE;
-
- //
- // create a mask bitmap and associated DC
- //
- hbmMask = CreateBitmap(dx, dy, 1, 1, NULL);
-
- if (!hbmMask)
- goto errorDC;
-
- // select the mask bitmap into the mono DC
-
- hbmT = (HBITMAP)SelectObject(hdcMask, hbmMask);
-
- // do a color to mono bitblt to build the mask
- // generate 1's where the source is equal to the background, else 0's
-
- SetBkColor(hdcS, rgbBk);
- BitBlt(hdcMask, 0, 0, dx, dy, hdcS, x0, y0, SRCCOPY);
-
- //
- // The first solution (using 4 blt's) does not flicker as much as the
- // second (3 Blt's) solution, but is slower!
- //
- #if 0
- // make all background pixels in the source BLACK
-
- SetBkColor(hdcS,rgbBk);
- BitBlt(hdcS,x0,y0,dx,dy,hdcMask,0,0,DSx);
-
- // do two bitblts to draw the image w/transparent mask
-
- SetBkColor(hdcD,rgbWhite);
- BitBlt(hdcD,x,y,dx,dy,hdcMask,0,0,DSa);
- BitBlt(hdcD,x,y,dx,dy,hdcS,x0,y0,DSx);
-
- // restore all background pixels in the source
-
- SetBkColor(hdcS,rgbBk);
- BitBlt(hdcS,x0,y0,dx,dy,hdcMask,0,0,DSx);
- #else
- // do a MaskBlt to copy the bitmap to the dest
-
- SetBkColor(hdcD,rgbWhite);
- BitBlt(hdcD,x,y,dx,dy,hdcS, x0,y0,DSx);
- BitBlt(hdcD,x,y,dx,dy,hdcMask,0 ,0 ,DSa);
- BitBlt(hdcD,x,y,dx,dy,hdcS, x0,y0,DSx);
- #endif
-
- f = TRUE;
-
- SelectObject(hdcMask, hbmT);
- DeleteObject(hbmMask);
-
- //
- // Restore the DC colors
- //
- SetBkColor(hdcS,rgbBkS);
- SetBkColor(hdcD,rgbBk);
- SetTextColor(hdcD,rgbFg);
-
- errorDC:
- DeleteDC(hdcMask);
- return f;
- }
-
-
- //
- // draw a DIB bitmap treating the background color of the DC as transparent
- //
- int TransStretchDIBits(HDC hdc,
- WORD DstX, WORD DstY, WORD DstDX, WORD DstDY,
- WORD SrcX, WORD SrcY, WORD SrcDX, WORD SrcDY,
- LPVOID lpBits, LPBITMAPINFO lpbi,
- WORD wUsage, DWORD rop)
- {
- struct {
- BITMAPINFOHEADER bih;
- WORD aw[256];
- } biPal;
-
- struct {
- BITMAPINFOHEADER bih;
- DWORD argb[256];
- } biRgb;
-
- WORD FAR *pw;
- DWORD FAR *prgb;
- COLORREF rgbBk;
- HPALETTE hpal;
- WORD wPalBk;
- WORD wPalBlack;
- WORD wPalWhite;
- int i;
-
- //
- // see if the device supports this call directly
- //
- // otherwise we need to simulate it.
- //
- #ifndef WIN32
- if (GetDeviceCaps(hdc, CAPS1) & C1_TRANSPARENT)
- {
- WORD w;
- BOOL f;
-
- w = SetBkMode(hdc, TRANSPARENT1);
-
- f = StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
- SrcX,SrcY,SrcDX,SrcDY,
- lpBits, lpbi, wUsage, rop);
- SetBkMode(hdc, w);
- return f;
- }
- #endif
-
- //
- // we want to do the equivelent of a MaskBlt, but we dont have to
- // create multiple masks and things, we just change the color
- // table of DIB, (aren't DIBs great)
- //
- // we will use the two pass MaskBlt()
- //
- // AND the dest with a DIB that has '1' where the trans color is
- // '0' otherwise
- //
- // OR the dest with a DIB that has '0' where the trans color is
- //
-
- rgbBk = GetBkColor(hdc);
-
- if (wUsage == DIB_PAL_COLORS)
- {
- // get current palette.
- hpal = SelectPalette(hdc, (HPALETTE)GetStockObject(DEFAULT_PALETTE), FALSE);
- SelectPalette(hdc, hpal, FALSE);
-
- // get the index of the background color (and black)
- //
- // NOTE it is *very* important that the palette has
- // black and white in it (*real* black and white, not
- // PC_RESERVED or PC_NOCOLAPSE) we are doing raster op's
- // and assume black==00, and white==FF
- //
- wPalBk = GetNearestPaletteIndex(hpal, rgbBk);
- wPalBlack = GetNearestPaletteIndex(hpal, rgbBlack);
- wPalWhite = GetNearestPaletteIndex(hpal, rgbWhite);
-
- //
- // copy the given BITMAPINFO over and munge it, to make our mask.
- // the usage is DIB_PAL_COLORS so we need to munge index's not
- // RGBs
- //
- biPal.bih = lpbi->bmiHeader;
- pw = (WORD FAR *)lpbi->bmiColors;
-
- for (i=0; i < (int)biPal.bih.biClrUsed; i++)
- {
- if (pw[i] == wPalBk)
- biPal.aw[i] = wPalWhite;
- else
- biPal.aw[i] = wPalBlack;
- }
-
- StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
- SrcX,SrcY,SrcDX,SrcDY,
- lpBits, (LPBITMAPINFO)&biPal, wUsage, DSa);
-
- for (i=0; i < (int)biPal.bih.biClrUsed; i++)
- {
- if (pw[i] == wPalBk)
- biPal.aw[i] = wPalBlack;
- else
- biPal.aw[i] = pw[i];
-
- }
-
- StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
- SrcX,SrcY,SrcDX,SrcDY,
- lpBits, (LPBITMAPINFO)&biPal, wUsage, DSx);
- }
- else
- {
- // the usage is DIB_RGB_COLORS so we need to munge rgb's not
- // index's
- //
- biRgb.bih = lpbi->bmiHeader;
- prgb = (DWORD FAR *)lpbi->bmiColors;
-
- for (i=0; i < (int)biPal.bih.biClrUsed; i++)
- {
- if (prgb[i] == RGBQ(rgbBk))
- biRgb.argb[i] = RGBQ(rgbWhite);
- else
- biRgb.argb[i] = RGBQ(rgbBlack);
- }
-
- StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
- SrcX,SrcY,SrcDX,SrcDY,
- lpBits, (LPBITMAPINFO)&biRgb, wUsage, DSa);
-
- for (i=0; i < (int)biPal.bih.biClrUsed; i++)
- {
- if (prgb[i] == RGBQ(rgbBk))
- biRgb.argb[i] = RGBQ(rgbBlack);
- else
- biRgb.argb[i] = prgb[i];
- }
-
- StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
- SrcX,SrcY,SrcDX,SrcDY,
- lpBits, (LPBITMAPINFO)&biPal, wUsage, DSx);
- }
-
- return TRUE;
- }
-